/**
 *******************************************************************************
 * @FileName  : dm_api.h
 * @Author    : GaoQiu
 * @CreateDate: 2020-02-18
 * @Copyright : Copyright(C) GaoQiu
 *              All Rights Reserved.
 *******************************************************************************
 *
 * The information contained herein is confidential and proprietary property of
 * GaoQiu and is available under the terms of Commercial License Agreement
 * between GaoQiu and the licensee in separate contract or the terms described
 * here-in.
 *
 * This heading MUST NOT be removed from this file.
 *
 * Licensees are granted free, non-transferable use of the information in this
 * file under Mutual Non-Disclosure Agreement. NO WARRENTY of ANY KIND is provided.
 *
 *******************************************************************************
 */

#ifndef DM_API_H_
#define DM_API_H_

#include "stack/hci_defs.h"
#include "hci_api.h"
#include "l2cap_api.h"
#include "smp_api.h"

/*! GAP Device Role */
#define DM_ROLE_MASTER             HCI_ROLE_MASTER
#define DM_ROLE_SLAVE              HCI_ROLE_SLAVE

/*! Secure Level */
#define DM_SEC_LEVEL_NONE           0x00
#define DM_SEC_LEVEL_ENC            0x01
#define DM_SEC_LEVEL_ENC_AUTH       0x02
#define DM_SEC_LEVEL_ENC_LESC       0x03

/*! The address type to use over the air or that is associated with a received address. */
#define DM_ADDR_PUBLIC              0x00  /*!< Public device address */
#define DM_ADDR_RANDOM              0x01  /*!< Random device address */
#define DM_ADDR_PUBLIC_IDENTITY     0x02  /*!< Public identity address (corresponds to resolved private address) */
#define DM_ADDR_RANDOM_IDENTITY     0x03  /*!< Random (static) identity address (corresponds to resolved private address) */
#define DM_ADDR_RANDOM_UNRESOLVED   0xFE  /*!< Random device address (Controller unable to resolve) */
#define DM_ADDR_NONE                0xFF  /*!< No address provided (anonymous) */


/*!  The advertising type indicates the connectable and discoverable nature of the advertising packets transmitted by a device. */
#define DM_ADV_CONN_UNDIRECT           0  /*!< Connectable undirected advertising.  Peer devices can scan and connect to this device. */
#define DM_ADV_CONN_DIRECT_HIGH_DUTY   1  /*!< Connectable directed advertising, high duty cycle.  Only a specified peer device can connect to this device. */
#define DM_ADV_SCAN_UNDIRECT           2  /*!< Scannable undirected advertising.  Peer devices can scan this device but cannot connect. */
#define DM_ADV_NONCONN_UNDIRECT        3  /*!< Non-connectable undirected advertising.  Peer devices cannot scan or connect to this device. */
#define DM_ADV_CONN_DIRECT_LOW_DUTY    4  /*!< Connectable directed advertising, low duty cycle.  Only a specified peer device can connect to this device. */

/*!   Advertising channel bit. */
#define DM_ADV_CHAN_37_BIT            (1 << 0)  /*!< Advertising channel 37. */
#define DM_ADV_CHAN_38_BIT            (1 << 1)  /*!< Advertising channel 38. */
#define DM_ADV_CHAN_39_BIT            (1 << 2)  /*!< Advertising channel 39. */
#define DM_ADV_CHAN_ALL               0x07      /*!< All advertising channels. */

/*!   ADV Filter Policy type */
#define DM_ADV_FILTER_NONE                0x00
#define DM_ADV_FILTER_ONLY_SCAN_REQ       0x01
#define DM_ADV_FILTER_ONLY_CONN_REQ       0x02
#define DM_ADV_FILTER_SCAN_AND_CONN_REQ   0x03

/*!  Initiator filter policy. */
#define DM_INIT_FILTER_PEER           0     /*!< Filter to only Peer addr and addr type. */
#define DM_INIT_FILTER_WL             1     /*!< Filter to only whitelist. */

/*! Scan type. */
#define DM_PASSIVE_SCAN               0
#define DM_ACTIVE_SCAN                1

/*!   Scan filter policy. */
#define DM_SCAN_FILTER_NONE            0    /*!< Accept all advertising packets. */
#define DM_SCAN_FILTER_WL_BIT          1    /*!< Accept from While List only. */
#define DM_SCAN_FILTER_RES_INIT_BIT    2    /*!< Accept directed advertisements with RPAs. */
#define DM_SCAN_FILTER_WL_OR_RES_INIT  3    /*!< Accept from White List or directed advertisements with RPAs. */


/*! ADV Data Type define. */
#define DM_ADV_TYPE_FLAGS                   0x01
#define DM_ADV_TYPE_INCOMP_UUIDS16          0x02
#define DM_ADV_TYPE_COMP_UUIDS16            0x03
#define DM_ADV_TYPE_INCOMP_UUIDS32          0x04
#define DM_ADV_TYPE_COMP_UUIDS32            0x05
#define DM_ADV_TYPE_INCOMP_UUIDS128         0x06
#define DM_ADV_TYPE_COMP_UUIDS128           0x07
#define DM_ADV_TYPE_INCOMP_NAME             0x08
#define DM_ADV_TYPE_COMP_NAME               0x09
#define DM_ADV_TYPE_TX_PWR_LVL              0x0A
#define DM_ADV_TYPE_SLAVE_ITVL_RANGE        0x12
#define DM_ADV_TYPE_SOL_UUIDS16             0x14
#define DM_ADV_TYPE_SOL_UUIDS128            0x15
#define DM_ADV_TYPE_SVC_DATA_UUID16         0x16
#define DM_ADV_TYPE_PUBLIC_TGT_ADDR         0x17
#define DM_ADV_TYPE_RANDOM_TGT_ADDR         0x18
#define DM_ADV_TYPE_APPEARANCE              0x19
#define DM_ADV_TYPE_ADV_ITVL                0x1A
#define DM_ADV_TYPE_SVC_DATA_UUID32         0x20
#define DM_ADV_TYPE_SVC_DATA_UUID128        0x21
#define DM_ADV_TYPE_URI                     0x24
#define DM_ADV_TYPE_MESH_PROV               0x29
#define DM_ADV_TYPE_MESH_MESSAGE            0x2A
#define DM_ADV_TYPE_MESH_BEACON             0x2B
#define DM_ADV_TYPE_MFG_DATA                0xFF

/*! Adv param define. */
typedef struct{
	uint16_t    minInterval;
	uint16_t    maxInterval;
	uint8_t     advType;
	uint8_t     ownAddrType;
	uint8_t     peerAddrType;
	uint8_t    *pPeerAddr;
	uint8_t     chnMap;
	uint8_t     filter;
}DmAdvParam_t;

/*! Adv data field define. */
typedef struct {
    uint8_t  length;
    uint8_t  type;
    uint8_t  value[0];
}DmAdvDataField_t;

/*! Adv data parse call-back define. */
typedef int (*DmAdvDataParseCback_t) (const DmAdvDataField_t *, void *);


/*! Scan param define. */
typedef struct{
	uint8_t    scanType;
	uint16_t   scanInterval;
	uint16_t   scanWindow;
	uint8_t    ownAddrType;
	uint8_t    scanFilter;
}DmScanParam_t;

/*! DM security control block. */
typedef struct{
	uint8_t   initiateSec;
	uint8_t   ioCap;
	uint8_t   oobEnable;
	uint8_t   auth;
	uint8_t   maxKeyLen;
	uint8_t   iKeyDist;
	uint8_t   rKeyDist;
	uint8_t   useDefPinCode;
	uint32_t  defPinCode;
}DmSecCb_t;

/*! DM call-back event. */
enum{
	/* Controller event. */
	DM_ADV_REPORT_IND,             /*!< Scan data received from peer device. */
	DM_CONN_OPEN_IND,              /*!< Connection opened. */
	DM_CONN_CLOSE_IND,             /*!< Connection closed. */
	DM_CONN_UPD_IND,               /*!< Connection update complete. */
	DM_CONN_DATA_LEN_CHANGE_IND,   /*!< Connection data length changed. */
	DM_CONN_ENC_IND,
	DM_CONN_ENC_FAILED_IND,
	DM_CONN_READ_REMOTE_VER_IND,
	DM_CONN_LE_READ_REMOTE_FEAT_IND,
	DM_CONN_AUTH_PAYLOAD_TO,
	DM_CONN_CH_SEL_IND,
	DM_CONN_PHY_UPD_IND,

	/* Host event. */
	DM_L2C_CONN_PARAM_UPD_IND,
	DM_SMP_PAIR_END_IND,
	DM_SMP_PIN_CODE_IND,
	DM_SMP_PIN_CODE_REQ,
};

/*!< Union for HCI event type */
typedef union{
	MdcMsgHdr_t                    hdr;

	/* Controller event. */
	//HCI BT event
	HciDisconnectCmplEvt_t         disconnectCmpl;
	HciEncChangeEvt_t              encChange;
	HciReadRemoteVerInfoCmplEvt_t  readRemoteVerInfoCmpl;
	HciHwErrorEvt_t                hwError;
	HciEncKeyRefreshCmpl_t         encKeyRefreshCmpl;
	//HciNumCmplPktEvt_t             numCmplPkts;

	//HCI LE event
	HciLeConnCmplEvt_t             leConnCmpl;           /*!< LE connection complete/enchance connection complete. */
	HciLeAdvReportEvt_t            leAdvReport;          /*!< LE advertising/direct advertising report. */
	HciLeConnUpdateCmplEvt_t       leConnUpdateCmpl;
	HciLeReadRemoteFeatCmplEvt_t   leReadRemoteFeatCmpl;
	//HciLeLtkReqEvt_t               leLtkReq;
	HciLeRemConnParamReqEvt_t      leRemConnParamReq;
	HciLeDataLenChangeEvt_t        leDataLenChange;
	HciLeP256CmplEvt_t             leP256Cmpl;
	HciLeGenDhKeyEvt_t             leGenDhKeyCmpl;
	HciLeChSelEvt_t                leChnSelInd;
	HciLePhyUpdCmplEvt_t           lePhyUpdCmpl;

	/* Host event. */
	L2cConnParamUpdInd_t           l2cConnParamUpdInd;
	SmpPairEndInd_t                smpPairEndInd;
	SmpPinCodeInd_t                smpPinCodeInd;
	SmpPinCodeReq_t                smpPinCodeReq;
}DmEvt_t;

//typedef HciEvt_t DmEvt_t;

/*! Custom Host Error Code -- BleState_t */
#define HOST_ERR_CODE_START        LL_ERR_CODE_MAX
enum{
	BLE_OK                          = 0,

	//ATT state code
	BLE_ERR_ATT_INVALID_HANDLE      = HOST_ERR_CODE_START,
	BLE_ERR_ATT_INVALID_PDU,
	BLE_ERR_ATT_INVALID_VALUE,
	BLE_ERR_ATT_SERVER_NOTIFY_NOT_ENABLED,
	BLE_ERR_ATT_SERVER_INDICATE_NOT_ENABLED,
	BLE_ERR_ATT_POOL_BUF_ALLOC_FAILED,

	//SMP state code
	BLE_ERR_SMP_POOL_BUF_ALLOC_FAILED,
	BLE_ERR_SMP_TIMEOUT,

	BLE_ERR_L2C_POOL_BUF_ALLOC_FAILED,

	//BLE_SDP state code
	BLE_SDP_DONE,
	BLE_ERR_SDP_TIMEOUT,
	BLE_ERR_SDP_BAD_DATA,

	//Common state code;
	BLE_ERR_BAD_DATA,
};

/*! Callback type. */
typedef void (*DmEvtCback_t)(DmEvt_t *pDmEvt);

void DM_Init(void);
void DM_EvtRegister(DmEvtCback_t pEvtCback);
void DM_ExecEvtCback(DmEvt_t *pMsg);

//ADV
void DM_AdvInit(void);
void DM_LE_SetAdvParam(DmAdvParam_t *pAdvParam);
void DM_LE_SetAdvData(uint8_t *pData, uint32_t len);
void DM_LE_SetScanRspData(uint8_t *pData, uint32_t len);
void DM_LE_SetAdvEnable(bool_t enable);
int  DM_LE_AdvFieldParse(const uint8_t *data, uint8_t length, DmAdvDataParseCback_t func, void *user_data);

//Scan
void DM_ScanInit(void);
void DM_LE_SetScanParam(DmScanParam_t *pScanParam);
void DM_LE_SetScanEnable(bool_t enable, bool_t dupFilt);
void DM_LE_CreateConn(LlInitParam_t *pInitParam, LlConnSpec_t *pConnSpec);
void DM_LE_CreateConnCancel(void);

//Connection
void DM_ConnInit(void);
void DM_Disconnect(uint16_t connHandle, uint8_t reason);

//Security
void DM_SecInit(void);
DmSecCb_t *DM_SecCb(void);
void DM_SecSetInitiateSecEnable(bool_t enable);
void DM_SecSetIoCap(uint8_t ioCap);
void DM_SecSetAuth(uint8_t auth);
void DM_SecSetDefPinCode(uint32_t pinCode, uint8_t enable);
void DM_SecSetKeyDist(uint8_t keyDist);
void DM_LE_StartEncrypt(uint16_t connHandle, uint8_t *pRand, uint16_t ediv, uint8_t *pLtk);

//Common
uint64_t DM_GetBdAddr(void);
uint8_t DM_ReadRemoteVerInfo(uint16_t connHandle);
void DM_LE_SetRandomAddr(uint8_t *pRand, uint32_t len);
uint8_t DM_LE_GetWhiteListSize(void);
void DM_LE_ClearWhiteList(void);
void DM_LE_AddDeviceToWhiteList(uint8_t addrType, uint8_t *pAddr);
void DM_LE_RemoveDeviceFromWhiteList(uint8_t addrType, uint8_t *pAddr);
uint8_t DM_LE_ReadRemoteFeat(uint16_t connHandle);
uint8_t DM_LE_DataLenExchange(uint16_t connHandle, uint16_t txOctets);

#endif /* DM_API_H_ */
